package com.snailhd.common.util;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpRequest;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author hd
 * @date 2019-07-26 16:01
 */

@Slf4j
public class HttpClientUtil {

    private static CloseableHttpClient httpclient = HttpClients.createDefault();

    public static String get(String url) throws Exception{
        return get(null,url, null, null);
    }

    public static String get(String url, Map<String,String> params) throws Exception{
        return get(null,url, params, null);
    }

    public static String get(String url, Map<String,String> params, Map<String,String> headers) throws Exception{
        return get(null, url, params, headers);
    }

    public static String get(String operateName,String url, Map<String,String> params) throws Exception{
        return get(operateName, url, params, null);
    }

    public static String get(String operateName, String url, Map<String,String> params, Map<String,String> headers) throws Exception {
        String result = null;
        CloseableHttpResponse response = null;
        try {
            response = httpclient.execute(buildHttpGet(url,params,headers));
            HttpEntity entity = response.getEntity();
            result = EntityUtils.toString(entity, "UTF-8");
            EntityUtils.consume(entity);
        } finally {
            log.info("请求[{}]：[url]:{} , [params]: {},[result]:{}, [headers]：{}",
                    operateName,url, JSON.toJSON(params),result,JSON.toJSONString(headers));
            if(response!=null){
                response.close();
            }
        }
        return result;
    }

    public final static int cache = 10*1024;


    /**
     * 构建一个HttpClient
     * @param url
     * @param params
     * @param headers
     * @return
     * @throws URISyntaxException
     */
    private static HttpGet buildHttpGet(String url,Map<String,String> params, Map<String,String> headers) throws URISyntaxException {
        URIBuilder uriBuilder = new URIBuilder(url);
        if(params!=null){
            params.forEach((k,v)-> uriBuilder.addParameter(k,v));
        }

        HttpGet httpGet = new HttpGet(uriBuilder.build());
        httpGet.setHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
        if(headers!=null){
            headers.forEach((k,v) ->  httpGet.setHeader(k,v));
        }

        return httpGet;
    }


    public static void download(String operateName,String filePath, String url, Map<String,String> params, Map<String,String> headers) throws Exception {
        InputStream is =  download( operateName , url,  params,  headers);
        File file = new File(filePath);
        file.getParentFile().mkdirs();
        FileOutputStream fos = new FileOutputStream(file);
        byte[] buffer = new byte[cache];
        int ch = 0;
        while ((ch = is.read(buffer)) != -1) {
            fos.write(buffer, 0, ch);
        }
        is.close();
        fos.flush();
        fos.close();
    }


    public static InputStream download(String operateName, String url, Map<String,String> params, Map<String,String> headers) throws Exception{

        CloseableHttpResponse response = null;
        InputStream is = null;
        try{
            response = httpclient.execute(buildHttpGet(url,params,headers));
            HttpEntity entity = response.getEntity();
            is = entity.getContent();
        }finally {
            log.info("请求[{}]：[url]:{} , [params]: {},[result]:{}, [headers]：{}",operateName,url, JSON.toJSON(params),JSON.toJSONString(headers));
        }
        return is;
    }

    public static void download(String operateName, File file, String downloadUrl, Map<String,String> params, Map<String,String> headers) throws Exception{

        URLConnection conn = null;
        FileOutputStream fos =  null;

        // 下载网络文件
        int bytesum = 0;
        int byteread = 0;

        StringBuilder sb = new StringBuilder(downloadUrl).append("?");

        if(params!=null){
            params.forEach((k,v) -> {
                sb.append(k).append("=").append(v).append("&");
            });
        }

        URL url = new URL(sb.toString());

        try {
            conn = url.openConnection();
            InputStream inStream = conn.getInputStream();
            fos = new FileOutputStream(file);

            byte[] buffer = new byte[cache];
            int length;
            while ((byteread = inStream.read(buffer)) != -1) {
                bytesum += byteread;
                fos.write(buffer, 0, byteread);
            }
        } finally {
            log.info("请求[{}]：[url]:{} , [params]: {}, [headers]：{}",operateName,sb.toString(), JSON.toJSON(params),JSON.toJSONString(headers));
            if(conn!=null){
                if(fos!=null){ fos.close();}
            }
        }

    }


    public static String post(String url) throws Exception{
        return post(null,url, null, null);
    }

    public static String post(String url, Map<String,String> params) throws Exception{
        return post(null,url, params, null);
    }


    public static String post(String url, Map<String,String> params, Map<String,String> headers) throws Exception{
        return post(null, url, params, headers);
    }

    public static String post(String operateName,String url, Map<String,String> params) throws Exception{
        return post(operateName, url, params, null);
    }

    public static String post(String operateName, String url, Map<String,String> params, Map<String,String> headers) throws Exception {

        CloseableHttpResponse response = null;
        String result = null;
        try {
            HttpPost httpPost = new HttpPost(url);
            httpPost.setHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
            if(headers!=null){
                headers.forEach((k,v) ->  httpPost.setHeader(k,v));
            }

            List<NameValuePair> nvps = new ArrayList<NameValuePair>();
            if(params!=null){
                params.forEach((k,v)-> nvps.add(new BasicNameValuePair(k, v)));
            }
            httpPost.setEntity(new UrlEncodedFormEntity(nvps));

            response = httpclient.execute(httpPost);

            HttpEntity entity = response.getEntity();
            result = EntityUtils.toString(entity, StandardCharsets.UTF_8);

            EntityUtils.consume(entity);
        } finally {
            log.info("请求[{}]：[url]:{}, [params]: {}, [result]:{}, [headers]:{}",
                    operateName,url, JSON.toJSON(params),result,JSON.toJSONString(headers));
            if(null!=response){
                response.close();
            }
        }
        return result;
    }


    public static String postJSON(String url, String params) throws Exception{
        return postJSON(null, url,  params, null);
    }

    public static String postJSON(String operateName,String url, String params) throws Exception{
        return postJSON(operateName, url,  params, null);
    }

    public static String postJSON(String url, String params,Map<String,String> headers) throws Exception{
        return postJSON(null, url,  params, headers);
    }

    /**
     * 模拟 POST JSON 请求
     * @param url 请求地址
     * @param params 请求参数
     * @return 返回值
     * @throws Exception 抛出异常
     */
    public static String postJSON(String operateName,String url, String params,Map<String,String> headers) throws Exception{
        CloseableHttpResponse response = null;
        String result = null;
        try{
            HttpPost httpPost = new HttpPost(url);
            httpPost.setHeader("Accept", "application/json");
            httpPost.setHeader("Content-Type", "application/json; charset=UTF-8");
            if(headers!=null){
                headers.forEach((k,v) ->  httpPost.setHeader(k,v));
            }
            HttpEntity se = new ByteArrayEntity(params.getBytes(StandardCharsets.UTF_8));
            httpPost.setEntity(se);
            response = httpclient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            result = EntityUtils.toString(entity, "UTF-8");
            EntityUtils.consume(entity);
        }finally {
            log.info("请求[{}]：[url]:{}, [params]: {}, [result]:{}, [headers]:{}",
                    operateName,url, JSON.toJSON(params),result,JSON.toJSONString(headers));
            if(null!=response){
                response.close();
            }
        }
        return result;
    }




}
